package com.service.impl;

import com.aop.SystemMail;
import com.dao.MemberDao;
import com.dao.MemberbuyrecordForMemeberDao;
import com.dto.BaseDto;
import com.dto.dataenum.MessageEnum;
import com.entity.Account;
import com.entity.Condition;
import com.entity.Member;
import com.entity.Memberbuyrecord;
import com.exception.CustomException;
import com.page.PageInfo;
import com.rabbitmq.RabbitUtil;
import com.service.AccountService;
import com.service.MemberService;
import com.utils.TimeDateUtils;
import com.vo.MailUser;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.List;
import java.util.Optional;
import java.util.Random;

@Service
public class MemberServiceImpl implements MemberService, AccountService {
    @Resource
    MemberDao memberDao;
    @Resource
    MemberbuyrecordForMemeberDao memberbuyrecordForMemeberDao;



    public BaseDto getAll()throws Exception{
        //枚举的具体值由三元表达式决定
        List<Member> members = memberDao.getAll();
        MessageEnum messageEnum = members.size()>0?MessageEnum.GETAllMEMBERSUCCESS:MessageEnum.ADDMEBERFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.settList(members);//将查询结果也放入dto
        return dto;
    }

    /**
     *
     * @param pageInfo
     * @return
     */
    //表示首先到 缓存管理器  myCache 找有没有数据，根据cacheId
    public BaseDto getMembersByPage(PageInfo pageInfo){
        //枚举的具体值由三元表达式决定
        List<Member> members = memberDao.getMembersByPage(pageInfo);
        MessageEnum messageEnum = members.size()>0?MessageEnum.GETMEMBERSBYPAGESUCCESS:MessageEnum.GETMEMBERSBYPAGEFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.settList(members);//将查询结果也放入dto
        return dto;
    }

    //表示首先到 缓存管理器  myCache 找有没有数据，根据cacheId
    @Cacheable(value = "myCache",key = "#cacheId")
    public BaseDto getMembersByPage(PageInfo pageInfo, String cacheId){
        //枚举的具体值由三元表达式决定
        List<Member> members = memberDao.getMembersByPage(pageInfo);
        MessageEnum messageEnum = members.size()>0?MessageEnum.GETMEMBERSBYPAGESUCCESS:MessageEnum.GETMEMBERSBYPAGEFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.settList(members);//将查询结果也放入dto
        return dto;
    }
    /**
     * 搜索分页查询
     * @param pageInfo
     * @return
     */
    public BaseDto searchMembersByPage(PageInfo pageInfo, List<Condition> conditions) throws ParseException {
        //枚举的具体值由三元表达式决定
        List<Member> members = memberDao.searchMembersByPage(pageInfo,conditions);
        MessageEnum messageEnum = members.size()>0?MessageEnum.SEARCHMEMBERSBYPAGESUCCESS:MessageEnum.SEARCHMBERSBYPAGEFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.settList(members);//将查询结果也放入dto
        return dto;
    }

    public BaseDto getMemberByMno(String mno)throws Exception{

        Member member = memberDao.getMemberByMno(mno);
        MessageEnum messageEnum = Optional.ofNullable(member).isPresent()?MessageEnum.GETMEMBERBYMNOSUCCESS:MessageEnum.GETMEMBERBYMNOFAIL;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.setT(member);//单个对象放入dto
        return dto;
    }

    /**
     * 根据主键查询对象的全部关联
     * @param mno
     * @return
     * @throws Exception
     */
    public BaseDto memberByMnoWithAll(String mno)throws Exception{

        Member member = memberDao.memberByMnoWithAll(mno);
        MessageEnum messageEnum = Optional.ofNullable(member).isPresent()?MessageEnum.GETMEMBERBYMNOSUCCESS:MessageEnum.GETMEMBERBYMNOFAIL;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.setT(member);//单个对象放入dto
        return dto;
    }




    public BaseDto add(Member member) throws Exception{
        String algorithmName = "md5";
        String username = member.getMname();
        String password = member.getMpwd();
        String salt1 = username;
        String salt2 = new SecureRandomNumberGenerator().nextBytes().toHex();
        int hashIterations = 3;//进行三次 hash
        SimpleHash hash = new SimpleHash(algorithmName, password, salt1 + salt2, hashIterations);
        String encodedPassword = hash.toHex();
        member.setMpwd(encodedPassword);

        Integer result = memberDao.add(member);
        MessageEnum messageEnum = result>0?MessageEnum.ADDMEMBERSUCCESS:MessageEnum.ADDMEBERFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.setT(member);
        return dto;
    }

    public BaseDto update(Member member) throws Exception{
        Integer result = memberDao.update(member);
        MessageEnum messageEnum = result>0?MessageEnum.UPDATEMEMBERSUCCESS:MessageEnum.UPDATEMEBERFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        return dto;
    }

    /**
     * 会员购买方案   增加会员积分 同时 增加一条购买记录
     * @param member
     * @return
     * @throws Exception
     */
    //指定事务的管理器，propagation定事务的传播行为，那些异常引发回滚rollbackFor
    @Transactional(value="transactionManager",propagation = Propagation.REQUIRED,rollbackFor={CustomException.class})
    public BaseDto buyProgram(Member member, String prno) throws Exception{
        Integer result = memberDao.update(member);
        //构建一个订单对象 提供根据时间 计算出的订单编号   会员编号 方案编号  评价（null）  金额（）
        Memberbuyrecord memberbuyrecord = new Memberbuyrecord(TimeDateUtils.getCurrDateAndTimeString(), TimeDateUtils.getCurrDate(),member.getMno(),prno,null,200);

       int rand = new Random().nextInt() % 2;
       if(rand == 1){
           throw new CustomException(MessageEnum.BUYPROGRAMEFAIl.getMsg());
       }

        memberbuyrecordForMemeberDao.add(memberbuyrecord);

        MessageEnum messageEnum = result>0?MessageEnum.BUYPROGRAMESUCCESS:MessageEnum.BUYPROGRAMEFAIl;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        return dto;
    }

    @Override
    public BaseDto getAccountByAccountName(String accountName) throws Exception{

        Member member = memberDao.getAccountByAccountName(accountName);
        MessageEnum messageEnum = Optional.ofNullable(member).isPresent()?MessageEnum.GETMEMBERBYMNOSUCCESS:MessageEnum.GETMEMBERBYMNOFAIL;
        BaseDto dto = new BaseDto(messageEnum);//将枚举的结果放入dto构造
        dto.setT(member);//单个对象放入dto
        return dto;
    }
}
